package com.tinyideatech.framework.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.wxpay.sdk.WXPayUtil;
import com.tinyideatech.common.utils.DateUtils;
import com.tinyideatech.common.utils.RedisUtil;
import com.tinyideatech.framework.dto.FTP;
import com.tinyideatech.system.entity.CarCode;
import com.tinyideatech.system.entity.CarDevice;
import com.tinyideatech.system.entity.CarOrder;
import com.tinyideatech.system.mapper.CarCodeMapper;
import com.tinyideatech.system.mapper.CarDeviceMapper;
import com.tinyideatech.system.mapper.CarOrderMapper;
import com.tinyideatech.system.service.ICarGoodsService;
import mypackage.DevelopmentServiceDelegate;
import mypackage.DevelopmentServiceServiceLocator;
import mypackage.Feature;
import mypackage.SerialNumber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.xml.rpc.ServiceException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


@Service
public class VerifyWxService {

    private static final Logger logger = LoggerFactory.getLogger(VerifyWxService.class);

    @Autowired
    private CarOrderMapper carOrderMapper;

    @Autowired
    private CarDeviceMapper carDeviceMapper;

    @Autowired
    private FTP ftp;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private CarCodeMapper carCodeMapper;

    @Autowired
    private ICarGoodsService goodsService;

    @Value("${wx.pay.mchKey}")
    private String key;

    /**
     * 微信支付下单处理
     *
     * @param result
     * @param deviceId
     * @param OutTradeNo
     */
    public boolean verifyWxPayUnifiedOrderResult(WxPayUnifiedOrderResult result, String deviceId, String OutTradeNo, Integer feature, String productId, String code, String expireTime) throws NullPointerException {
        if (result == null) {
            logger.error("请求出错");
            return false;
        }
        CarDevice device = null;
        CarCode carCode = null;
        try {
            // 更新code和device之间的关系
            CarDevice carDevice = carDeviceMapper.selectAllById(deviceId);
            if (carDevice == null) {
                // 如果这个没有绑定关系
                device = new CarDevice();
                device.setDeviceId(deviceId);
                device.setCreateBy("admin");
                device.setCreateTime(DateUtils.getNowDate());
                device.setDeviceAdas(code);
                device.setDeviceProperties("测试");
                int status = carDeviceMapper.insert(device);
                if (status > 0) {
                    carCode = new CarCode();
                    carCode.setDeviceId(deviceId);
                    carCode.setCreateTime(DateUtils.getNowDate());
                    carCode.setCode(code);

                    carCodeMapper.insert(carCode);
                    return parseOrder(result, deviceId, OutTradeNo, feature, expireTime, productId);
                }
            } else {

                // 2019-11-15 修改登录逻辑
                if (carDevice.getDeviceAdas() == null || carDevice.getDeviceAdas().equals("")) {
                    carDevice.setDeviceAdas(code);
                    int status = carDeviceMapper.updateById(carDevice);
                    if (status > 0) {
                        carCode = new CarCode();
                        carCode.setDeviceId(deviceId);
                        carCode.setCreateTime(DateUtils.getNowDate());
                        carCode.setCode(code);
                        carCodeMapper.insert(carCode);
                        return parseOrder(result, deviceId, OutTradeNo, feature, expireTime, productId);
                    }
                }

                return parseOrder(result, deviceId, OutTradeNo, feature, expireTime, productId);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return false;
    }


    private boolean parseOrder(WxPayUnifiedOrderResult result, String deviceId, String OutTradeNo, Integer feature, String expireTime, String productId) {

        // 预支付订单
        CarOrder preOrder = new CarOrder();
        logger.info(String.format("[订单处理:%s]", result));
        preOrder.setPrepayId(result.getPrepayId());
        preOrder.setDeviceId(deviceId);
        preOrder.setTradeType(result.getTradeType());
        preOrder.setFeature(feature);
        preOrder.setCreateTime(DateUtils.getNowDate());
        preOrder.setTotalFee(goodsService.getPrice(feature));
        preOrder.setBody(goodsService.getName(feature));
        preOrder.setId(OutTradeNo);
        preOrder.setTimeEnd(DateUtils.parseDate(expireTime));
        String codeUrlFtp = ftp.getFullPathImgFtp() + "wx" + OutTradeNo + ".png";
        preOrder.setQrcodeUrl(codeUrlFtp);
        logger.info(String.format("[预支付订单:%s]", preOrder));
        int orderInsert = carOrderMapper.insert(preOrder);
        if (orderInsert == 1) {
            logger.info(String.format("插入值为[%s]", preOrder));
            return true;
        }
        return false;
    }


    public String generateDetail(Integer f) {
        if (f == 1) {
            return "鑫洋泉激活码ADAS功能-BSD";
        } else if (f == 2) {
            return "鑫洋泉激活码ADAS功能-MOD";
        }
        return "鑫洋泉激活码ADAS功能-LDW";
    }

    private Integer parseFeature(Integer feature, CarCode carCode) {
        Integer code = carCode.getFeatures();
        List<Integer> result = sort(code, feature);
        int num = 0;
        for (int i = 0; i < result.size(); i++) {
            Double head = Math.pow(10, result.size() - (i + 1));
            num = num + result.get(i) * (head.intValue());
        }
        return num;
    }

    /**
     * 微信支付回调处理
     *
     * @param orderNotifyResult
     * @return
     * @throws Exception
     */
    public boolean verifyNotifyResult(WxPayOrderNotifyResult orderNotifyResult, String xmlData) throws Exception {
        try {
            if (!orderNotifyResult.getResultCode().equals("SUCCESS")) {
                // 支付失败，记录流水失败
                logger.error("支付失败");
                return false;
            } else {

                CarOrder query = carOrderMapper.selectOne(
                        new QueryWrapper<CarOrder>().eq("id", orderNotifyResult.getOutTradeNo()));
                logger.info(String.format("{%s}", orderNotifyResult));
                if (!(WXPayUtil.isSignatureValid(xmlData, key))) {
                    logger.error("微信支付失败，失败原因：签名不通过");
                    return false;
                }
                if (query == null) {
                    logger.error("微信支付失败，失败原因：未找到相应的订单号");
                    return false;
                } else {
                    // 因网络原因造成的回调重复
                    if (!query.getTransactionId().equals("")) {
                        return false;
                    }
                    if (redisUtil.containsValueKey(orderNotifyResult.getOutTradeNo())) {
                        return false;
                    } else {
                        redisUtil.cacheValue(orderNotifyResult.getOutTradeNo(), "-adas");
                    }

                    // 业务一：更新订单表
                    query.setTransactionId(orderNotifyResult.getTransactionId());
                    query.setIsSubscribe(orderNotifyResult.getIsSubscribe());
                    query.setOpenid(orderNotifyResult.getOpenid());
                    query.setUpdateTime(DateUtils.getNowDate());
                    int update = carOrderMapper.updateById(query);
                    if (update > 0) {
                        CarDevice carDevice = carDeviceMapper.selectOne(
                                new QueryWrapper<CarDevice>().eq("device_id", query.getDeviceId()));
                        CarCode carCode = carCodeMapper.selectOne(
                                new QueryWrapper<CarCode>().eq("device_id", carDevice.getId()));
                        String code = carCode.getCode();
                        boolean resultEdit = parseCode(code, query.getFeature(), carCode, carDevice);
                        if (resultEdit) {
                            return true;
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(String.format("未知错误：[%s]", e.getMessage()));
            return false;
        }
        return false;
    }


    /**
     * 组装微信成功xml
     *
     * @param return_code
     * @param return_msg
     * @return
     */
    private String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }


    /**
     * 更新激活码feature
     *
     * @param code
     * @param target
     * @return
     */
    private boolean parseCode(String code, Integer target, CarCode carCode, CarDevice carDevice) {
        DevelopmentServiceServiceLocator locator =
                new DevelopmentServiceServiceLocator();
        DevelopmentServiceDelegate service;
        try {
            service = locator.getDevelopmentServicePort();
            SerialNumber serialNumber = service.getSnDetail(code);
            Feature[] features = serialNumber.getFeature();
            for (Feature feature : features) {
                if (feature.getName().equals("ADAS")) {
                    // 更新设备激活状态为1,2,3
                    Integer num = parseFeature(target, carCode);
                    feature.setValue(num);
                    carCode.setFeatures(num);
                    carDevice.setDeviceActiveStatus(num);
                    carDevice.setActiceTime(DateUtils.getNowDate());
                }
            }
            // TODO: repeat three times to end up update sn features
            service.setSnMultiFeature(code, features);

            int update = carCodeMapper.updateById(carCode);
            carDeviceMapper.updateById(carDevice);
            if (update > 0) {
                return true;
            }
        } catch (ServiceException | RemoteException e) {
            e.printStackTrace();
        }
        return false;
    }


    private static List<Integer> sort(Integer sql, Integer comparable) {
        List<Integer> a = new ArrayList<>();
        if (sql.equals(0)) {
            a.add(comparable);
            return a;
        }
        if (sql / 10 >= 1) {
            if (sql / 10 < 10) {
                a.add(sql / 10);
                a.add(sql % 10);
            }
        } else {
            a.add(sql);
        }
        a.add(comparable);
        Collections.sort(a);
        return a;
    }
}
